package com.leyantech.ecp.agenx.web.handler;

import com.leyantech.ecp.agenx.common.config.Constants;
import com.leyantech.ecp.agenx.common.di.JWTAuthProvider;
import com.leyantech.ecp.agenx.web.AuthMessage;
import com.leyantech.ecp.agenx.web.filter.AuthFilter;

import com.google.inject.Inject;
import com.google.inject.Singleton;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.vertx.core.http.HttpHeaders;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.AuthenticationHandler;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * @author eahau, {@literal <eahau@foxmail.com>}
 * @date 2022-10-31.
 */
@Slf4j
@Singleton
public class AuthHandler implements AuthenticationHandler {

  private final List<AuthFilter> filters;

  private final JWTAuthProvider jwtAuthProvider;

  @Inject
  public AuthHandler(List<AuthFilter> filters, JWTAuthProvider jwtAuthProvider) {
    this.filters = filters;
    this.jwtAuthProvider = jwtAuthProvider;
  }

  @Override
  public void handle(RoutingContext context) {
    final JsonObject jsonObject = context.body().asJsonObject();
    final String errorMessage = AuthMessage.check(jsonObject);
    if (!errorMessage.isEmpty()) {
      context.response()
          .setStatusCode(HttpResponseStatus.BAD_REQUEST.code())
          .send(errorMessage);
      return;
    }

    final AuthMessage authMessage = jsonObject.mapTo(AuthMessage.class);

    log.info("auth start {}", authMessage);

    for (AuthFilter filter : filters) {
      if (!filter.test(authMessage)) {
        context.fail(HttpResponseStatus.UNAUTHORIZED.code());
        return;
      }
    }

    final JsonObject claims = new JsonObject()
        .put(Constants.STORE_ID_FIELD, authMessage.getStoreId())
        .put(Constants.ASSISTANT_ID_FIELD, authMessage.getAssistantId())
        .put("assistant_name", authMessage.getAssistantName())
        .put("client_version", authMessage.getClientVersion())
        .put("client_uuid", authMessage.getClientUuid());

    final String token = jwtAuthProvider.get().generateToken(claims);

    log.info("generateToken done, send token");

    context.response().putHeader(HttpHeaders.AUTHORIZATION, token);
    context.end()
        .onFailure(throwable -> log.error("send token failed", throwable));
  }

  public void warmup() {
    final AuthMessage authMessage = new JsonObject("{\n"
        + "    \"store_id\": \"191781350\",\n"
        + "    \"assistant_id\": \"100295789\",\n"
        + "    \"assistant_name\": \"蒋道理\",\n"
        + "    \"client_version\": \"1.0.0\",\n"
        + "    \"client_uuid\": \"123456789\"\n"
        + "}")
        .mapTo(AuthMessage.class);
    for (int i = 0; i < 200; i++) {
      for (AuthFilter filter : filters) {
        try {
          filter.test(authMessage);
        } catch (Exception ignore) {
        }
      }
    }
  }

}
